﻿using System;
using System.Collections.Generic;
using System.Net;
using System.IO;
using System.Text;

namespace LoveMusic.Helpers
{
    public class Mp3FileApi
    {
        public List<String> GetMp3Urls(string artistName, string songName)
        {
            artistName = RemoveSpecialCharactersExceptAmpersand(artistName);
            songName = RemoveSpecialCharactersExceptAmpersand(songName);
            
            List<String> mp3Urls = new List<string>();
            string searchUrl = string.Empty;
            string html = string.Empty;
            string artistNameSearch = string.Empty;
            string songNameSearch = string.Empty;

            #region skreemr

            artistNameSearch = artistName.Replace(" ", "+");
            songNameSearch = songName.Replace(" ", "+");
            searchUrl = @"http://skreemr.com/results.jsp?q=" + artistNameSearch + "+" + songNameSearch;

            html = GetResponse(searchUrl);
            if (html == null)
                html = GetResponseStandard(searchUrl);


            if (html != null && !html.Contains("No results for"))
                mp3Urls = ParseXMLSkreemr(html);

            #endregion

            #region Mp3 realm

            artistNameSearch = artistName.Replace(" ", "%20");
            songNameSearch = songName.Replace(" ", "%20");
            searchUrl = @"http://mp3realm.org/search?q=" + artistNameSearch + "%20" + songNameSearch;
            
            html = GetResponse(searchUrl);
            if (html == null)
                html = GetResponseStandard(searchUrl);
            

            if (html!=null && !html.Contains("No Results"))
                mp3Urls = ParseXMLRealmOrg(html);

            #endregion

            #region Playlist
            // probably doesn't work.

            #endregion Playlist.com

            #region wrzuta --bad

            ////$url = 'http://' . $url[0] . '/sr/f/' . $url[2] . '/.mp3';
            //artistNameSearch = artistName.Replace(".", " ");
            //songNameSearch = songName.Replace(".", " ");
            //artistNameSearch = artistNameSearch.Replace(" ", "%20");
            //songNameSearch = songNameSearch.Replace(" ", "%20");
            
            //searchUrl = @"http://www.wrzuta.pl/szukaj/audio/" + artistNameSearch + "%20" + songNameSearch;
            //html = GetResponse(searchUrl);

            //if (html == null)
            //    html = GetResponseStandard(searchUrl);

            //if (html!=null)
            //    if (html.Contains("info_msg") == false)
            //        foreach (string mp3Url in ParseXMLWrzuta(html))
            //            mp3Urls.Add(mp3Url);

            #endregion wrzuta

            #region 4Shared

            if (mp3Urls.Count == 0)
            {  // add this songs only if other source return empty
                artistNameSearch = artistName.Replace(" ", "+");
                songNameSearch = songName.Replace(" ", "+");
                searchUrl = @"http://search.4shared.com/network/search.jsp?sortType=1&sortOrder=1&sortmode=3&searchName=" + artistNameSearch + "+" + songNameSearch + "&searchmode=3&searchName=" + artistNameSearch + "+" + songNameSearch + "&searchDescription=&searchExtention=mp3&sizeCriteria=atleast&sizevalue=10&start=0";
                html = GetResponse(searchUrl);
                if (html!=null && html.Contains("No file(s) found"))
                    foreach (string mp3Url in ParseXML4Shared(html))
                        mp3Urls.Add(mp3Url);
            }

            #endregion

            return mp3Urls;
        }

        private List<string> ParseXMLSkreemr(string html)
        {
            List<string> outString = new List<string>();

            try
            {
                string[] parts = html.Split(new string[] { "Download MP3: <a" }, StringSplitOptions.None);
                

                for (int i = 1; i < parts.Length; i++)
                {
                    string mp3Url = GetFirstMiddleString(parts[i], "href=\"", "\"");
                    
                    if (mp3Url.Contains(".mp3"))
                        outString.Add(mp3Url);
                }
            }
            catch (Exception ex)
            {
                TraceLog.TimeWrite(ex, "ParseXMLWrzuta()");
            }

            return outString;
        }

        /// <summary>
        /// Find the mp3s from the wrzuta site
        /// </summary>
        /// <param name="html"></param>
        /// <returns></returns>
        private List<string> ParseXMLWrzuta(string html)
        {
            List<string> outString = new List<string>();

            try
            {
                string[] parts = html.Split(new string[] { "<div id=\"user_aud_list\">" }, StringSplitOptions.None);
                parts = parts[1].Split(new string[] { "<div class=\"file_mini_user\">" }, StringSplitOptions.None);

                for (int i = 1; i < parts.Length; i++)
                {
                    string middle = GetFirstMiddleString(parts[i], "<a href=\"http://", "\"");
                    string[] subParts = middle.Split(new string[] { "/" }, StringSplitOptions.None);
                    string mp3Url = "http://" + subParts[0] + "/sr/f/" + subParts[2] + "/.mp3";

                    //string textHtml = GetResponse(mp3Url);
                    outString.Add(mp3Url);
                }
            }
            catch (Exception ex)
            {
                TraceLog.TimeWrite(ex, "ParseXMLWrzuta()");
            }

            return outString;
        }


        /// <summary>
        /// Find the mp3 links in the html for 4Shared html
        /// Start = "<div class=\"imgbox\" align=\"center\">\n                          <a href=\"
        /// End = \" target=\"_blank\"\n
        /// </summary>
        /// <param name="html"></param>
        /// <returns></returns>
        private List<String> ParseXML4Shared(string html)
        {
            String subUrls = string.Empty;
            string subHtml = string.Empty;
            List<string> outString = new List<string>();
            try
            {
                string[] parts = html.Split(new string[] { "<div class=\"imgbox\" align=\"center\">\n                          <a href=\"" }, StringSplitOptions.None);

                //Jump the first one and start from i=1
                // Get the urls that containg the mp3 links
                for (int i = 1; i < parts.Length; i++)
                {
                    int endOfLink = parts[i].IndexOf("\" target=\"_blank\"\n");

                    subUrls = parts[i].Substring(0, endOfLink);
                    subHtml = GetResponse(subUrls);
                    string[] subParts = subHtml.Split(new string[] { "function startDownload(){\r\n    //document.downloadForm.submit();\r\n    window.location = \"" }, StringSplitOptions.None);
                    for (int j = 1; j < subParts.Length; j++)
                    {
                        int subEndOfLink = subParts[j].IndexOf(".mp3") + 4;
                        outString.Add(subParts[j].Substring(0, subEndOfLink));
                    }
                }
            }
            catch (Exception ex)
            {
                TraceLog.TimeWrite(ex, "ParseXML4Shared()");
            }
            return outString;
        }

        /// <summary>
        /// Find the mp3 links in the html of mp3Realm
        /// Play(\\ - link begins
        /// ')" - link ends
        /// </summary>
        /// <param name="xml"></param>
        /// <returns></returns>
        private List<String> ParseXMLRealmOrg(string html)
        {
            List<String> outString = new List<string>();
            try
            {
                string[] parts = html.Split(new string[] { "Play('" }, StringSplitOptions.None);

                //Jump the first one and start from i=1
                for (int i = 1; i < parts.Length; i++)
                {
                    int endOfLink = parts[i].IndexOf("')");
                    outString.Add(parts[i].Substring(0, endOfLink));
                }
            }
            catch (Exception ex)
            {
                TraceLog.TimeWrite(ex, "ParseXMLRealmOrg()");
            }
            return outString;
        }

        /// <summary>
        /// Get the xml 
        /// </summary>
        /// <param name="url"></param>
        /// <returns></returns>
        /// 
        private string GetResponse(string url)
        {
            try
            {
                WebClient wc = new WebClient();
                wc.Headers.Add(HttpRequestHeader.AcceptEncoding, "gzip");

                //that solves the problem partially:
                wc.Proxy = null;

                wc.Encoding = System.Text.Encoding.UTF8;
                wc.Headers.Add("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.0.3705;)");


                using (ICSharpCode.SharpZipLib.GZip.GZipInputStream stream = new ICSharpCode.SharpZipLib.GZip.GZipInputStream(wc.OpenRead(url)))
                {
                    using (StreamReader reader = new StreamReader(stream))
                    {
                        return reader.ReadToEnd();
                    }
                }
            }
            catch (Exception ex)
            {
                TraceLog.TimeWrite(ex, "GetResponse url=" + url);
                return null;
            }
        }

        private string GetResponseStandard(string url)
        {
            try
            {
                WebClient wc = new WebClient();

                using (Stream stream = wc.OpenRead(url))
                {
                    using (StreamReader reader = new StreamReader(stream))
                    {
                        return reader.ReadToEnd();
                    }
                }
            }
            catch (Exception ex)
            {
                TraceLog.TimeWrite(ex, "GetResponse url=" + url);
                return null;
            }
        }

        private string RemoveSpecialCharactersExceptAmpersand(string str)
        {
            StringBuilder sb = new StringBuilder();
            foreach (char c in str)
            {
                if ((c == ' ') || (c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || c == '_' || c == '&')
                {
                    sb.Append(c);
                }
            }
            return sb.ToString();
        }

        private string GetFirstMiddleString(string input, string start, string end)
        {
            string[] parts = input.Split(new string[] { start }, StringSplitOptions.None);
            parts = parts[1].Split(new string[] { end }, StringSplitOptions.None);
            return parts[0];
        }

    }
}